﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Core;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.Common;

namespace NUnitForVSTS.NUnitTest
{
    /// <summary>
    /// Event dispatcher for the discovery of unittests
    /// </summary>
    class TestLoaderDiscoverEventDispatcher: TestLoaderEventDispatcher
    {
        public TestLoaderDiscoverEventDispatcher(Guid testRunId): base(testRunId)
        {
        }

        /// <summary>
        /// Project data
        /// </summary>
        private ProjectData _data;

        /// <summary>
        /// Executes when the test is loaded
        /// </summary>
        /// <param name="test"></param>
        protected override void TestIsLoaded(NUnit.Core.ITest test)
        {
            base.TestIsLoaded(test);
            ConvertLoadedTest(test, LoadedLocationInLoader, _data);
        }

        /// <summary>
        /// Discovers the tests.
        /// </summary>
        /// <param name="location">The location.</param>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public IEnumerable<ITestElement> DiscoverTests(string location, ProjectData data)
        {
            _data = data;
            CurrentTests = new Dictionary<string, ITestElement>();

            LoadAssemblyInLoader(location);
            LoadTest(string.Empty);
            if (AreTests())
            {
                UnloadTests();
            }
            _data = null;
            return CurrentTests.Values;
        }

        /// <summary>
        /// Adds the loaded test.
        /// </summary>
        /// <param name="test">The test.</param>
        /// <param name="location">The location.</param>
        /// <param name="data">The data.</param>
        private void ConvertLoadedTest(ITest test, string location, ProjectData data)
        {
            Stack<ITest> todo = new Stack<ITest>();
            todo.Push(test);
            while (todo.Count != 0)
            {
                test = todo.Pop();
                if (!test.IsSuite)
                {
                    if (test.RunState != NUnit.Core.RunState.Ignored)
                    {
                        Trace.WriteLine("Test: " + test.TestName.FullName + " Converted");
                        UnitTest element = new UnitTest(test, location);
                        element.ProjectData = data;
                        element.Storage = location;
                        CurrentTests.Add(test.TestName.FullName, element);
                    }
                }
                if (test.Tests != null)
                {
                    foreach (ITest subTest in test.Tests)
                    {
                        todo.Push(subTest);
                    }
                }
            }
        }

    }
}
